package br.academia.negocio;

import org.hibernate.HibernateException;

import br.academia.arq.dao.EstadoDAO;
import br.academia.arq.erros.DAOException;
import br.academia.arq.erros.NegocioException;
import br.academia.dominio.Estado;
import br.academia.util.Validador;

/** 
 * Processador para validação de negócio de operações
 * relacionadas a Estado
 * 
 * @see Estado
 */
public class EstadoProcessador extends AbstractProcessador<Estado>{

	@Override
	public void execute(TipoOperacao operacao, Estado obj) throws NegocioException{
		try {
			if(operacao.equals(CADASTRAR)){
				validarCadastro(obj);
				cadastrar(obj);
			}else if(operacao.equals(ALTERAR)){
				validarAlteracao(obj);
				alterar(obj);
			}else if(operacao.equals(REMOVER)){
				validarRemocao(obj);
				remover(obj);
			}
		} catch (HibernateException e) {
			e.printStackTrace();
			throw new NegocioException("Não foi possível realizar a operação. Contate a administração do sistema.");
		} catch (DAOException e) {
			throw new NegocioException(e.getMessage());
		}
	}
	
	/**
	 * Método que valida se o nome setado em um Estado já tem um correspondente
	 * com relação à sigla, no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void validarNome(Estado obj) throws NegocioException, HibernateException, DAOException{
		EstadoDAO dao = null;
		boolean erro = false;
		
		try {
			dao = getDAO(EstadoDAO.class);
			
			Estado estado = dao.findEstadoByNome(obj.getNome());
			
			if(!Validador.isEmpty(estado)){
				if(estado.getId() != obj.getId()){
					erro = true;
				}
			}
			
			if(erro){
				throw new NegocioException("Um outro Estado já foi cadastrado com o nome \"" + obj.getNome() + "\".");
			}
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que valida se o nome setado em um Estado já tem um correspondente
	 * com relação à sigla, no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void validarSigla(Estado obj) throws NegocioException, HibernateException, DAOException{
		EstadoDAO dao = null;
		boolean erro = false;
		
		try {
			dao = getDAO(EstadoDAO.class);
			
			Estado estado = dao.findEstadoBySigla(obj.getSigla());
			
			if(!Validador.isEmpty(estado)){
				if(estado.getId() != obj.getId()){
					erro = true;
				}
			}
			
			if(erro){
				throw new NegocioException("Um outro Estado já foi cadastrado com o nome \"" + obj.getNome() + "\".");
			}
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para o cadastro
	 * de um Estado novo no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarCadastro(Estado obj) throws HibernateException, NegocioException, DAOException{
		validarNome(obj);
		validarSigla(obj);
	}
	
	/**
	 * Método que insere um Estado no banco de dados.
	 * @param obj
	 * @throws NegocioException
	 * @throws HibernateException
	 * @throws DAOException
	 */
	private void cadastrar(Estado obj) throws NegocioException, HibernateException, DAOException{
		EstadoDAO dao = null;
		
		try {
			dao = getDAO(EstadoDAO.class);
			
			dao.save(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para a alteração
	 * de um Estado no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarAlteracao(Estado obj) throws NegocioException, HibernateException, DAOException{
		if(Validador.isEmpty(obj)){
			throw new NegocioException("Você selecionou um Estado inválido.");
		}else{
			EstadoDAO dao = null;
			Estado estado = null;
			
			try {
				dao = getDAO(EstadoDAO.class);
				
				estado = dao.findEstadoByNome(obj.getNome());
			}finally{
				if(dao != null){
					dao.close();
				}
			}
			
			if(!Validador.isEmpty(estado)){
				validarSigla(obj);
				validarNome(obj);
			}
		}
	}
	
	/**
	 * Método que atualiza um Estado no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void alterar(Estado obj) throws NegocioException, HibernateException, DAOException{
		EstadoDAO dao = null;
		
		try {
			dao = getDAO(EstadoDAO.class);
			
			dao.update(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
	
	/**
	 * Método que faz as validações necessárias para a remoção
	 * de um Estado no banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void validarRemocao(Estado obj) throws NegocioException, HibernateException, DAOException{
		if(Validador.isEmpty(obj)){
			throw new NegocioException("Você selecionou um Estado inválido.");
		}else{
			EstadoDAO dao = null;
			Estado Estado = null;
			
			try {
				dao = getDAO(EstadoDAO.class);
				
				Estado = dao.findByPrimaryKey(obj.getId(), Estado.class);
			}finally{
				if(dao != null){
					dao.close();
				}
			}
			
			if(Validador.isEmpty(Estado)){
				throw new NegocioException("Não foi possível encontrar o Estado selecionado no nosso banco de dados.");
			}
		}
	}
	
	/**
	 * Método que remove um Estado do banco de dados.
	 * @param obj
	 * @throws HibernateException
	 * @throws NegocioException
	 * @throws DAOException
	 */
	private void remover(Estado obj) throws NegocioException, HibernateException, DAOException{
		EstadoDAO dao = null;
		
		try {
			dao = getDAO(EstadoDAO.class);
			
			dao.delete(obj);
		}finally{
			if(dao != null){
				dao.close();
			}
		}
	}
}
